#include <iostream>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include "Lock.hpp"
using namespace std;
// 模拟多线程抢票
// int ticket = 1000;
// 1.全局静态初始化互斥量不用销毁互斥量
// pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

// 2.还有局部静态分配互斥量
// static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 然后将这个锁传入pthread_create(),从而使线程能拿到这把锁

// 3.还可以通过结构体传入锁

// pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
// void *getTickets(void *args)
// {
//     char* name=static_cast<char*>(args);
//     while(1)
//     {
//         //pthread_mutex_lock(&mutex);   阻塞式加锁
//         pthread_mutex_trylock(&mutex); //非阻塞式加锁
//         if(ticket>0)
//         {
//             usleep(1000);
//             printf("%s:抢到%d号票了 \n",name,ticket);
//             ticket--;
//             //解锁
//             pthread_mutex_unlock(&mutex);
//             usleep(100);
//         }
//         else
//         {
//             cout << name << "] 已经放弃抢票了, 因为没有了..." << endl;
//             pthread_mutex_unlock(&mutex);  //得加上这个，如果判断不大于0就会进来
//             break;
//         }
//     }
//     return nullptr;
// }

// int main()
// {
//     //首先初始化锁
//     pthread_mutex_init(&mutex,nullptr);
//     pthread_t tid1;
//     pthread_t tid2;
//     pthread_t tid3;
//     pthread_t tid4;
//     pthread_create(&tid1,nullptr,getTickets,(void*)"thread1");
//     pthread_create(&tid2,nullptr,getTickets,(void*)"thread2");
//     pthread_create(&tid3,nullptr,getTickets,(void*)"thread3");
//     pthread_create(&tid4,nullptr,getTickets,(void*)"thread4");

//     //回收线程
//     int n = pthread_join(tid1, nullptr);
//     cout << n << ":" << strerror(n) << endl;
//     n = pthread_join(tid2, nullptr);
//     cout << n << ":" << strerror(n) << endl;
//     n = pthread_join(tid3, nullptr);
//     cout << n << ":" << strerror(n) << endl;
//     n = pthread_join(tid4, nullptr);
//     cout << n << ":" << strerror(n) << endl;

//     //最后销毁锁
//     //pthread_mutex_destroy(&mutex);

//     return 0;
// }



/*

int ticket = 1000;
Mutex mutex;

void *getTickets(void *args)
{
    char *name = static_cast<char *>(args);
    // 类的生命周期结束后，锁就会被析构，这种方式叫做  临时的LockGuard对象， RAII风格的锁！
    while (1)
    {
        Lock_Guard lock_guard(&mutex);
        if (ticket > 0)
        {
            usleep(1000);
            ticket--;
            printf("%s:抢到%d号票了 \n",name,ticket);
            // 解锁
            usleep(100);
        }
        else
        {
             cout << name << "] 已经放弃抢票了, 因为没有了..." << endl;
             break;
        }
    }
    return nullptr;
}


int main()
{
    //使用锁类，不用开头初始化
    pthread_t tid1;
    pthread_t tid2;
    pthread_t tid3;
    pthread_t tid4;
    pthread_create(&tid1, nullptr, getTickets, (void *)"thread1");
    pthread_create(&tid2, nullptr, getTickets, (void *)"thread2");
    pthread_create(&tid3, nullptr, getTickets, (void *)"thread3");
    pthread_create(&tid4, nullptr, getTickets, (void *)"thread4");

    // 回收线程
    int n = pthread_join(tid1, nullptr);
    cout << n << ":" << strerror(n) << endl;
    n = pthread_join(tid2, nullptr);
    cout << n << ":" << strerror(n) << endl;
    n = pthread_join(tid3, nullptr);
    cout << n << ":" << strerror(n) << endl;
    n = pthread_join(tid4, nullptr);
    cout << n << ":" << strerror(n) << endl;

    // 最后销毁锁
    // pthread_mutex_destroy(&mutex);

    return 0;
}

*/

/*
//死锁
pthread_mutex_t mutexA;
pthread_mutex_t mutexB;
int ticket=1000;


void *getTicketsA(void *args)
{
    char *name = static_cast<char *>(args);
    // 类的生命周期结束后，锁就会被析构，这种方式叫做  临时的LockGuard对象， RAII风格的锁！
    while (1)
    {
        pthread_mutex_lock(&mutexA);
        sleep(1);

        pthread_mutex_lock(&mutexB);
        if (ticket > 0)
        {
            usleep(1000);
            ticket--;
            printf("%s:抢到%d号票了 \n",name,ticket);
            // 解锁
            usleep(100);
        }
        else
        {
            cout << name << "] 已经放弃抢票了, 因为没有了..." << endl;
            break;
        }
    }
    return nullptr;
}

void *getTicketsB(void *args)
{
    char *name = static_cast<char *>(args);
    // 类的生命周期结束后，锁就会被析构，这种方式叫做  临时的LockGuard对象， RAII风格的锁！
    while (1)
    {
        pthread_mutex_lock(&mutexB);
        sleep(1);

        pthread_mutex_lock(&mutexA);
        if (ticket > 0)
        {
            usleep(1000);
            ticket--;
            printf("%s:抢到%d号票了 \n",name,ticket);
            // 解锁
            usleep(100);
        }
        else
        {
            cout << name << "] 已经放弃抢票了, 因为没有了..." << endl;
            break;
        }
    }
    return nullptr;
}

int main()
{
    pthread_t tid1;
    pthread_t tid2;

    pthread_create(&tid1, nullptr, getTicketsA, (void *)"thread1");
    pthread_create(&tid2, nullptr, getTicketsB, (void *)"thread2");

    pthread_join(tid1,nullptr);
    pthread_join(tid2,nullptr);

    return 0;
}

*/



////单执行流同样会产生死锁 

pthread_mutex_t mutex;
int main()
{

    pthread_mutex_lock(&mutex);
    pthread_mutex_lock(&mutex); //锁已经申请了，会被挂起等待锁归还才会被唤醒，但是锁在自己手上

    return 0;
}

